package io.github.enbool.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

import io.github.enbool.bean.ResultBean;
import io.github.enbool.exception.BaseException;
import io.github.enbool.exception.CheckException;
import io.github.enbool.exception.RecordNotFoundException;
import lombok.extern.slf4j.Slf4j;



/**
 * 处理和包装异常
 * 
 * @author 晓风轻 https://github.com/xwjie/PLMCodeTemplate
 */
@Aspect
@Component
@Order(-5)
@Slf4j
public class ControllerAOP {
	
	@Pointcut("execution(public io.github.enbool.bean.ResultBean *(..))")
	public void aop() {}

	@Around("aop()")
	public Object handlerControllerMethod(ProceedingJoinPoint pjp) {
		long startTime = System.currentTimeMillis();

		ResultBean<?> result;

		try {
			result = (ResultBean<?>) pjp.proceed();
			
			// 如果需要打印入参，可以从这里取出打印
			// Object[] args = pjp.getArgs();

			// 本次操作用时（毫秒）
			long elapsedTime = System.currentTimeMillis() - startTime;
			log.info("[{}]use time: {}", pjp.getSignature(), elapsedTime);
		} catch (Throwable e) {
			result = handlerException(pjp, e);
		}

		return result;
	}

	private ResultBean<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
		ResultBean<?> result = new ResultBean<>();

		// 已知异常【注意：已知异常不要打印堆栈，否则会干扰日志】
		// 校验出错，参数非法
		if (e instanceof CheckException || e instanceof IllegalArgumentException) {
			result.setMsg(e.getLocalizedMessage());
			result.setCode(ResultBean.CHECK_FAIL);
		}		
		
		/*else if(e instanceof UnauthorizedUserException) {
			throw new UnauthorizedUserException(e.getMessage());
		}
		
		else if(e instanceof NoPermissionException) {
			throw new NoPermissionException(e.getMessage());
		}
		*/
		else if (e instanceof RecordNotFoundException) {
			result.setMsg(e.getMessage());
			result.setCode(ResultBean.RECORD_NOT_FOUND);
		}
		
		
	
		// 违反数据完整性 
		else if (e instanceof DataIntegrityViolationException) {
			result.setMsg(e.getMessage());
			result.setCode(ResultBean.DATA_INTEGRITY_VIOLATION);
		}
		// 其他异常
		else if (e instanceof BaseException) {
			result.setMsg(e.getMessage());
			result.setCode(((BaseException) e).getCode());
		} else {
			log.error(pjp.getSignature() + " error ", e);

			// TODO 未知的异常，应该格外注意，可以发送邮件通知等
			result.setMsg(e.toString());
			result.setCode(ResultBean.UNKNOWN_EXCEPTION);
		}

		return result;
	}
}
